🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / discovery / src / commonTest / kotlin / org / meshtastic / feature / discovery / DiscoveryTerminalCoordinatorTest.kt
Displaying Raw • Download
feature/discovery/src/commonTest/kotlin/org/meshtastic/feature/discovery/DiscoveryTerminalCoordinatorTest.kt bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 8.61 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.discovery
Tff7b72import T7ee787kotlinx.coroutines.CompletableDeferred
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.CoroutineStart
Tff7b72import T7ee787kotlinx.coroutines.async
Tff7b72import T7ee787kotlinx.coroutines.test.runCurrent
Tff7b72import T7ee787kotlinx.coroutines.test.runTest
Tff7b72import T7ee787org.meshtastic.core.common.di.ApplicationCoroutineScope
Tff7b72import T7ee787org.meshtastic.core.database.entity.DiscoverySessionEntity
Tff7b72import T7ee787org.meshtastic.core.database.entity.DiscoverySessionStatus
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.testing.FakeMeshPrefs
Tff7b72import T7ee787org.meshtastic.core.testing.FakeServiceRepository
Tff7b72import T7ee787org.meshtastic.proto.Config
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertTrue
Tff7b72class T56d364DiscoveryTerminalCoordinatorTest Tb4b4b4{
T8b949e/** Adapts the finite test scope to the application-scope contract for coordinator-only tests. */
Tff7b72private Tff7b72fun Td2a8ffapplicationScopeTb4b4b4(Te6edf3scopeTb4b4b4: Te6edf3CoroutineScopeTb4b4b4)Tb4b4b4: Te6edf3ApplicationCoroutineScope Tff7b72=
Tff7b72object Tb4b4b4: T56d364ApplicationCoroutineScope Tb4b4b4{
Tff7b72override Tff7b72val Te6edf3coroutineContext Tff7b72= Te6edf3scopeTb4b4b4.Te6edf3coroutineContext
Tb4b4b4}
Tf0883e@Test
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongMethodTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffjoinedRestoreFailurePublishesTheDowngradedOutcomeTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3device Tff7b72= Ta5d6ff"Ta5d6ffx:DEVICETa5d6ff"
Tff7b72val Te6edf3discoveryDao Tff7b72= Te6edf3SharedInMemoryDiscoveryDaoTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3sessionId Tff7b72=
Te6edf3discoveryDaoTb4b4b4.Te6edf3insertSessionTb4b4b4(
Te6edf3DiscoverySessionEntityTb4b4b4(
Te6edf3timestamp Tff7b72= T79c0ff1LTb4b4b4,
Te6edf3presetsScanned Tff7b72= Ta5d6ff"Ta5d6ffSHORT_FASTTa5d6ff"Tb4b4b4,
Te6edf3homePreset Tff7b72= Ta5d6ff"Ta5d6ffLONG_FASTTa5d6ff"Tb4b4b4,
Te6edf3completionStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3IN_PROGRESSTb4b4b4,
Te6edf3deviceAddress Tff7b72= Te6edf3deviceTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e// Model a device switch so the shared restore resolves false immediately; retry policy is tested separately.
Tff7b72val Te6edf3meshPrefs Tff7b72= Te6edf3FakeMeshPrefsTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3setDeviceAddressTb4b4b4(Ta5d6ff"Ta5d6ffx:OTHERTa5d6ff"Tb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3serviceRepository Tff7b72= Te6edf3FakeServiceRepositoryTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3setConnectionStateTb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3ConnectedTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3appScope Tff7b72= Te6edf3applicationScopeTb4b4b4(Tff7b72thisTb4b4b4)
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3DiscoveryTestRadioControllerTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3selectedDeviceAddress Tff7b72= Te6edf3device Tb4b4b4}
Tff7b72val Te6edf3homeRestorer Tff7b72=
Te6edf3DiscoveryHomeRestorerTb4b4b4(
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3serviceRepository Tff7b72= Te6edf3serviceRepositoryTb4b4b4,
Te6edf3discoveryDao Tff7b72= Te6edf3discoveryDaoTb4b4b4,
Te6edf3applicationScope Tff7b72= Te6edf3appScopeTb4b4b4,
Te6edf3meshPrefs Tff7b72= Te6edf3meshPrefsTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3publishedOutcomes Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3coordinator Tff7b72=
Te6edf3DiscoveryTerminalCoordinatorTb4b4b4(
Te6edf3discoveryDao Tff7b72= Te6edf3discoveryDaoTb4b4b4,
Te6edf3homeRestorer Tff7b72= Te6edf3homeRestorerTb4b4b4,
Te6edf3applicationScope Tff7b72= Te6edf3appScopeTb4b4b4,
Te6edf3onSessionUpdated Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3onTerminalCompleted Tff7b72= Tb4b4b4{ Te6edf3publishedOutcomes Tff7b72+Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4,
Te6edf3cancelScan Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3restorePlan Tff7b72=
Te6edf3DiscoveryHomeRestorePlanTb4b4b4(
Te6edf3sessionId Tff7b72= Te6edf3sessionIdTb4b4b4,
Te6edf3deviceAddress Tff7b72= Te6edf3deviceTb4b4b4,
Te6edf3loraConfig Tff7b72= Te6edf3ConfigTb4b4b4.Te6edf3LoRaConfigTb4b4b4(Te6edf3use_preset Tff7b72= Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3primaryChannel Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3restorePrimaryChannel Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3finalStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3STOPPEDTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3ownerRequest Tff7b72=
Te6edf3DiscoveryTerminalRequestTb4b4b4(
Te6edf3sessionId Tff7b72= Te6edf3sessionIdTb4b4b4,
Te6edf3restorePlan Tff7b72= Te6edf3restorePlanTb4b4b4,
Te6edf3pendingStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3RESTORE_PENDING_STOPPEDTb4b4b4,
Te6edf3outcome Tff7b72= Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3CancelledTb4b4b4,
Te6edf3awaitRestore Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3shouldGenerateAi Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3joinedRequest Tff7b72=
Te6edf3ownerRequestTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3pendingStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3RESTORE_PENDING_COMPLETETb4b4b4,
Te6edf3outcome Tff7b72= Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3SuccessTb4b4b4,
Te6edf3awaitRestore Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3owner Tff7b72= Te6edf3asyncTb4b4b4(Te6edf3start Tff7b72= Te6edf3CoroutineStartTb4b4b4.Te6edf3UNDISPATCHEDTb4b4b4) Tb4b4b4{ Te6edf3coordinatorTb4b4b4.Te6edf3completeTb4b4b4(Te6edf3ownerRequestTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3joined Tff7b72= Te6edf3asyncTb4b4b4(Te6edf3start Tff7b72= Te6edf3CoroutineStartTb4b4b4.Te6edf3UNDISPATCHEDTb4b4b4) Tb4b4b4{ Te6edf3coordinatorTb4b4b4.Te6edf3completeTb4b4b4(Te6edf3joinedRequestTb4b4b4) Tb4b4b4}
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3ownerTb4b4b4.Te6edf3isCompletedTb4b4b4, Ta5d6ff"Ta5d6ffterminal owner did not completeTa5d6ff"Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3CancelledTb4b4b4, Te6edf3ownerTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3joinedTb4b4b4.Te6edf3isCompletedTb4b4b4, Ta5d6ff"Ta5d6ffjoined restore follow-up did not completeTa5d6ff"Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3FailedTb4b4b4, Te6edf3joinedTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(
Te6edf3listOfTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3CancelledTb4b4b4, Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3FailedTb4b4b4)Tb4b4b4,
Te6edf3publishedOutcomesTb4b4b4,
Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(
Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3RESTORE_PENDING_FAILEDTb4b4b4,
Te6edf3discoveryDaoTb4b4b4.Te6edf3getSessionTb4b4b4(Te6edf3sessionIdTb4b4b4)Tff7b72?.Te6edf3completionStatusTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tf0883e@Test
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongMethodTa5d6ff"Tb4b4b4)
Tff7b72fun Td2a8ffjoinedOutcomeDoesNotOverwriteStateAfterTerminalResetTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3discoveryDao Tff7b72= Te6edf3SharedInMemoryDiscoveryDaoTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3appScope Tff7b72= Te6edf3applicationScopeTb4b4b4(Tff7b72thisTb4b4b4)
Tff7b72val Te6edf3sessionId Tff7b72=
Te6edf3discoveryDaoTb4b4b4.Te6edf3insertSessionTb4b4b4(
Te6edf3DiscoverySessionEntityTb4b4b4(
Te6edf3timestamp Tff7b72= T79c0ff1LTb4b4b4,
Te6edf3presetsScanned Tff7b72= Ta5d6ff"Ta5d6ffSHORT_FASTTa5d6ff"Tb4b4b4,
Te6edf3homePreset Tff7b72= Ta5d6ff"Ta5d6ffLONG_FASTTa5d6ff"Tb4b4b4,
Te6edf3completionStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3IN_PROGRESSTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3homeRestorer Tff7b72=
Te6edf3DiscoveryHomeRestorerTb4b4b4(
Te6edf3radioController Tff7b72= Te6edf3DiscoveryTestRadioControllerTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3serviceRepository Tff7b72= Te6edf3FakeServiceRepositoryTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3discoveryDao Tff7b72= Te6edf3discoveryDaoTb4b4b4,
Te6edf3applicationScope Tff7b72= Te6edf3appScopeTb4b4b4,
Te6edf3meshPrefs Tff7b72= Te6edf3FakeMeshPrefsTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3publishedOutcomes Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3coordinator Tff7b72=
Te6edf3DiscoveryTerminalCoordinatorTb4b4b4(
Te6edf3discoveryDao Tff7b72= Te6edf3discoveryDaoTb4b4b4,
Te6edf3homeRestorer Tff7b72= Te6edf3homeRestorerTb4b4b4,
Te6edf3applicationScope Tff7b72= Te6edf3appScopeTb4b4b4,
Te6edf3onSessionUpdated Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3onTerminalCompleted Tff7b72= Tb4b4b4{ Te6edf3publishedOutcomes Tff7b72+Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4,
Te6edf3cancelScan Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3joinedEntered Tff7b72= Te6edf3CompletableDeferredTff7b72<Tffa657UnitTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3releaseJoined Tff7b72= Te6edf3CompletableDeferredTff7b72<Tffa657UnitTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3ownerRequest Tff7b72=
Te6edf3DiscoveryTerminalRequestTb4b4b4(
Te6edf3sessionId Tff7b72= Te6edf3sessionIdTb4b4b4,
Te6edf3restorePlan Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3pendingStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3COMPLETETb4b4b4,
Te6edf3outcome Tff7b72= Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3SuccessTb4b4b4,
Te6edf3awaitRestore Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3shouldGenerateAi Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3joinedRequest Tff7b72= Te6edf3ownerRequestTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3pendingStatus Tff7b72= Te6edf3DiscoverySessionStatusTb4b4b4.Te6edf3FAILEDTb4b4b4)
Tff7b72val Te6edf3owner Tff7b72= Te6edf3asyncTb4b4b4(Te6edf3start Tff7b72= Te6edf3CoroutineStartTb4b4b4.Te6edf3UNDISPATCHEDTb4b4b4) Tb4b4b4{ Te6edf3coordinatorTb4b4b4.Te6edf3completeTb4b4b4(Te6edf3ownerRequestTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3joined Tff7b72=
Te6edf3asyncTb4b4b4(Te6edf3start Tff7b72= Te6edf3CoroutineStartTb4b4b4.Te6edf3UNDISPATCHEDTb4b4b4) Tb4b4b4{
Te6edf3coordinatorTb4b4b4.Te6edf3completeTb4b4b4(
Te6edf3joinedRequestTb4b4b4,
Te6edf3beforeFinalize Tff7b72= Tb4b4b4{
Te6edf3joinedEnteredTb4b4b4.Te6edf3completeTb4b4b4(Tffa657UnitTb4b4b4)
Te6edf3releaseJoinedTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)
Te6edf3errorTb4b4b4(Ta5d6ff"Ta5d6ffdatabase unavailableTa5d6ff"Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3joinedEnteredTb4b4b4.Te6edf3isCompletedTb4b4b4, Ta5d6ff"Ta5d6ffjoined follow-up did not enter after owner completionTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3ownerTb4b4b4.Te6edf3isCompletedTb4b4b4, Ta5d6ff"Ta5d6ffterminal owner did not complete before resetTa5d6ff"Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3SuccessTb4b4b4, Te6edf3ownerTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3coordinatorTb4b4b4.Te6edf3resetForScanTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3releaseJoinedTb4b4b4.Te6edf3completeTb4b4b4(Tffa657UnitTb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3joinedTb4b4b4.Te6edf3isCompletedTb4b4b4, Ta5d6ff"Ta5d6ffjoined follow-up did not complete after releaseTa5d6ff"Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3FailedTb4b4b4, Te6edf3joinedTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3listOfTb4b4b4(Te6edf3DiscoveryScanStateTb4b4b4.Te6edf3CompletionOutcomeTb4b4b4.Te6edf3SuccessTb4b4b4)Tb4b4b4, Te6edf3publishedOutcomesTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.07s